﻿open Clexer
open System.Text
open Microsoft.FSharp.Text.Lexing
open Microsoft.FSharp.Text

type Lexeme = 
  {
    name : string
    value : string
  }

let ExecWithTimeMeasure proc = 
    let time' = System.DateTime.UtcNow
    let result = proc ()
    let time'' = System.DateTime.UtcNow
    result, time'' - time'

let toLexeme (t: token) : Lexeme = 
    match t with
    | IDENT x -> {name = "IDENT"; value = (fst x)}
    | QUALIFIER x -> {name = "QUALIFIER"; value = (fst x) }
    | CST_CHAR x -> {name = "CST_CHAR"; value = (fst x).ToString()}
    | CST_WCHAR x -> {name = "CST_WCHAR"; value = (fst x).ToString()}
    | CST_INT x -> {name = "CST_INT"; value = (fst x)}
    | CST_FLOAT x -> {name = "CST_FLOAT"; value = (fst x)}
    | NAMED_TYPE x -> {name = "NAMED_TYPE"; value = (fst x)}
    | CST_STRING x -> {name = "CST_STRING"; value = (fst x).ToString()}
    | CST_WSTRING x -> {name = "CST_WSTRING"; value = (fst x).ToString()}
    | EOF -> {name = "EOF"; value = ""}
    | CHAR _ -> {name = "CHAR"; value = ""}
    | INT _ -> {name = "INT"; value = ""}
    | BOOL _ -> {name = "BOOL"; value = ""}
    | DOUBLE _ -> {name = "DOUBLE"; value = ""}
    | FLOAT _ -> {name = "FLOAT"; value = ""}
    | VOID _ -> {name = "VOID"; value = ""}
    | INT64 _ -> {name = "INT64"; value = ""}
    | INT32 _ -> {name = "INT32"; value = ""}
    | ENUM _ -> {name = "ENUM"; value = ""}
    | STRUCT _ -> {name = "STRUCT"; value = ""}
    | TYPEDEF _ -> {name = "TYPEDEF"; value = ""}
    | UNION _ -> {name = "UNION"; value = ""}
    | SIGNED _ -> {name = "SIGNED"; value = ""}
    | UNSIGNED _ -> {name = "UNSIGNED"; value = ""}
    | LONG _ -> {name = "LONG"; value = ""}
    | SHORT _ -> {name = "SHORT"; value = ""}
    | VOLATILE _ -> {name = "VOLATILE"; value = ""}
    | EXTERN _ -> {name = "EXTERN"; value = ""}
    | STATIC _ -> {name = "STATIC"; value = ""}
    | CONST _ -> {name = "CONST"; value = ""}
    | RESTRICT _ -> {name = "RESTRICT"; value = ""}
    | AUTO _ -> {name = "AUTO"; value = ""}
    | REGISTER _ -> {name = "REGISTER"; value = ""}
    | THREAD _ -> {name = "THREAD"; value = ""}
    | SIZEOF _ -> {name = "SIZEOF"; value = ""}
    | ALIGNOF _ -> {name = "ALIGNOF"; value = ""}
    | EQ -> {name = "EQ"; value = ""}
    | PLUS_EQ -> {name = "PLUS_EQ"; value = ""}
    | MINUS_EQ -> {name = "MINUS_EQ"; value = ""}
    | STAR_EQ -> {name = "STAR_EQ"; value = ""}
    | SLASH_EQ -> {name = "SLASH_EQ"; value = ""}
    | PERCENT_EQ -> {name = "PERCENT_EQ"; value = ""}
    | AND_EQ -> {name = "AND_EQ"; value = ""}
    | PIPE_EQ -> {name = "PIPE_EQ"; value = ""}
    | CIRC_EQ -> {name = "CIRC_EQ"; value = ""}
    | INF_INF_EQ -> {name = "INF_INF_EQ"; value = ""}
    | SUP_SUP_EQ -> {name = "SUP_SUP_EQ"; value = ""}
    | ARROW -> {name = "ARROW"; value = ""}
    | DOT -> {name = "DOT"; value = ""}
    | EQ_EQ -> {name = "EQ_EQ"; value = ""}
    | EXCLAM_EQ -> {name = "EXLAM_EQ"; value = ""}
    | INF -> {name = "INF"; value = ""}
    | SUP -> {name = "SUP"; value = ""}
    | INF_EQ -> {name = "INF_EQ"; value = ""}
    | SUP_EQ -> {name = "SUP_EQ"; value = ""}
    | PLUS _ -> {name = "PLUS"; value = ""}
    | MINUS _ -> {name = "MINUS"; value = ""}
    | STAR _ -> {name = "STAR"; value = ""}
    | SLASH -> {name = "SLASH"; value = ""}
    | PERCENT -> {name = "PERCENT"; value = ""}
    | TILDE _ -> {name = "TILDE"; value = ""}
    | AND _ -> {name = "AND"; value = ""}
    | PIPE _ -> {name = "PIPE"; value = ""}
    | CIRC _ -> {name = "CIRC"; value = ""}
    | EXCLAM _ -> {name = "EXCLAM"; value = ""}
    | AND_AND _ -> {name = "AND_AND"; value = ""}
    | PIPE_PIPE -> {name = "PIPE_PIPE"; value = ""}
    | INF_INF -> {name = "INF_INF"; value = ""}
    | SUP_SUP -> {name = "SUP_SUP"; value = ""}
    | PLUS_PLUS _ -> {name = "PLUS_PLUS"; value = ""}
    | MINUS_MINUS _ -> {name = "MINUS_MINUS"; value = ""}
    | RPAREN _ -> {name = "RPAREN"; value = ""}
    | LPAREN _ -> {name = "LPAREN"; value = ""}
    | RBRACE _ -> {name = "RBRACE"; value = ""}
    | LBRACE _ -> {name = "LBRACE"; value = ""}
    | LBRACKET -> {name = "LBRACKET"; value = ""}
    | RBRACKET -> {name = "RBRACKET"; value = ""}
    | COLON -> {name = "COLON"; value = ""}
    | SEMICOLON _ -> {name = "SEMICOLON"; value = ""}
    | COMMA -> {name = "COMMA"; value = ""}
    | ELLIPSIS -> {name = "ELLIPSIS"; value = ""}
    | QUEST -> {name = "QUEST"; value = ""}
    | BREAK _ -> {name = "BREAK"; value = ""}
    | CONTINUE _ -> {name = "CONTINUE"; value = ""}
    | GOTO _ -> {name = "GOTO"; value = ""}
    | RETURN _ -> {name = "RETURN"; value = ""}
    | SWITCH _ -> {name = "SWITCH"; value = ""}
    | CASE _ -> {name = "CASE"; value = ""}
    | DEFAULT _ -> {name = "DEFAULT"; value = ""}
    | WHILE _ -> {name = "WHILE"; value = ""}
    | DO _ -> {name = "DO"; value = ""}
    | FOR _ -> {name = "FOR"; value = ""}
    | IF _ -> {name = "IF"; value = ""}
    | TRY _ -> {name = "TRY"; value = ""}
    | EXCEPT _ -> {name = "EXCEPT"; value = ""}
    | FINALLY _ -> {name = "FINALLY"; value = ""}
    | ELSE -> {name = "ELSE"; value = ""}
    | ATTRIBUTE _ -> {name = "ATTRIBUTE"; value = ""}
    | INLINE _ -> {name = "INLINE"; value = ""}
    | ASM _ -> {name = "ASM"; value = ""}
    | TYPEOF _ -> {name = "TYPEOF"; value = ""}
    | FUNCTION__ _ -> {name = "FUNCTION"; value = ""}
    | PRETTY_FUNCTION__ _ -> {name = "PRETTY_FUNCTION__"; value = ""}
    | LABEL__ -> {name = "LABEL__"; value = ""}
    | BUILTIN_VA_ARG _ -> {name = "BUILTIN_VA_ARG"; value = ""}
    | ATTRIBUTE_USED _ -> {name = "ATTRIBUTE_USED"; value = ""}
    | BUILTIN_VA_LIST -> {name = "BUILTIN_VA_LIST"; value = ""}
    | BLOCKATTRIBUTE -> {name = "BLOCKATTRIBUTE"; value = ""}
    | BUILTIN_TYPES_COMPAT _ -> {name = "BUILTIN_TYPES_COMPAT"; value = ""}
    | BUILTIN_OFFSETOF _ -> {name = "BUILTIN_OFFSETOF"; value = ""}
    | DECLSPEC _ -> {name = "DECLSPEC"; value = ""}
    | MSASM x -> {name = "MSASM"; value = (fst x)}
    | MSATTR x -> {name = "MSATTR"; value = (fst x)}
    | PRAGMA_LINE x -> {name = "PRAGMA_LINE"; value = (fst x)}
    | PRAGMA _ -> {name = "PRAGMA"; value = ""}
    | PRAGMA_EOL -> {name = "PRAGMA_EOL"; value = ""}
    | AT_TRANSFORM _ -> {name = "AT_TRANSFORM"; value = ""}
    | AT_TRANSFORMEXPR _ -> {name = "AT_TRANSFORMEXPR"; value = ""}
    | AT_SPECIFIER _ -> {name = "AT_SPECIFIER"; value = ""}
    | AT_EXPR _ -> {name = "AT_EXPR"; value = ""}
    | AT_NAME -> {name = "AT_NAME"; value = ""}
    | DIRECTIVE_DEFINE _ -> {name = "DIRECTIVE_DEFINE"; value = ""}
    | DIRECTIVE_INCLUDE x -> {name = "DIRECTIVE_INCLUDE"; value = (fst x).Trim()}
    | DIRECTIVE_IF _ -> {name = "DIRECTIVE_IF"; value = ""}
    | DIRECTIVE_ELSE _ -> {name = "DIRECTIVE_ELSE"; value = ""}
    | DIRECTIVE_IFDEF _ -> {name = "DIRECTIVE_IFDEF"; value = ""}
    | DIRECTIVE_IFNDEF _ -> {name = "DIRECTIVE_IFNDEF"; value = ""}
    | DIRECTIVE_ELIF _ -> {name = "DIRECTIVE_ELIF"; value = ""}
    | DIRECTIVE_ENDIF -> {name = "DIRECTIVE_ENDIF"; value = ""}
    | DIRECTIVE_EOL -> {name = "DIRECTIVE_EOL"; value = ""}
    | COMMENT x -> {name = "COMMENT"; value = (fst x)}
    | COMMENT_ONELINE x -> {name = "COMMENT_ONELINE"; value = (fst x)}
    
let runTest i test = 
    let (r,t) = ExecWithTimeMeasure test 
    printf "Test #%d\n Tokens count:%d\n Execution time(msec):%.3f\n" i r t.TotalMilliseconds 

let runTest1  =  (let p = Clexer.init @"..\..\test.c"
                  let example = seq {
                    while not p.IsPastEndOfStream do
                            yield Clexer.initial p  
                    }  
                  example |> Seq.map (toLexeme) |> Seq.iter (printfn "%A\n"))
runTest1

(*
let example = seq {
                    while not p.IsPastEndOfStream do
                            yield Clexer.initial p  
                    } in
let is_brace x =
    match x with
        | LBRACE _ -> true
        | RBRACE _ -> true
        | _ -> false
//let braces = Seq.filter is_brace example
let braces = example
let writer = new System.IO.StreamWriter(@"..\..\result.out")
//let res = Seq.toList example
//List.iter (fprintfn writer "%A ") res
//Seq.iter (printfn "%A ") braces
let len = (Seq.toList braces).Length
(*
Seq.iter (fun x ->
               len <- len + 1
               if (len mod 10 = 0) then
                   printfn "%d" len
               ()
         ) braces
*)
fprintfn writer "%d " len
//Seq.iter (fprintfn writer "%A ") braces
//Seq.iter (printfn "%A ") example
fprintfn writer "Working time: %s" ((System.DateTime.Now.Subtract startTime).ToString())
writer.Close()
//System.Console.ReadLine();
*)